﻿using Inovout.Data.Redis;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.SessionState;

namespace Inovout.Web.SessionState
{
    public class RedisSessionStateStore : SessionStateStoreProviderBase
    {
        private RedisConnection redisConnection;
        public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
        {
            return new SessionStateStoreData(new SessionStateItemCollection(),
                    SessionStateUtility.GetSessionStaticObjects(context), timeout);
        }

        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            throw new NotImplementedException();
        }

        public override void Dispose()
        {
            redisConnection.Dispose();
        }

        public override void EndRequest(HttpContext context)
        {
        }

        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            throw new NotImplementedException();
        }

        public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            actions = SessionStateActions.None;
            lockAge = TimeSpan.Zero;
            lockId = null;
            locked = false;

            redisConnection.Open();
            StringCommand stringCommand = redisConnection.CreateStringCommand();
            var reulst = stringCommand.Get(string.Format("{0}_{1}", sessionKeyPrefix, id), (long)SessionStateConfig.Timeout.TotalSeconds);
            reulst = reulst.Trim("'".ToCharArray());
            Dictionary<string, object> itemDic = JsonConvert
                .DeserializeObject<Dictionary<string, object>>(reulst);

            redisConnection.Close();

            SessionStateItemCollection sessionItems =
        new SessionStateItemCollection();

            foreach (var item in itemDic)
            {
                sessionItems[item.Key] = item.Value;
            }
            SessionStateStoreData sessionStateStoreData = new SessionStateStoreData(sessionItems, SessionStateUtility.GetSessionStaticObjects(context), SessionStateConfig.Timeout.Minutes);

            return sessionStateStoreData;
        }
        public SessionStateSection SessionStateConfig { get; private set; }
        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            Configuration cfg =
              WebConfigurationManager.OpenWebConfiguration(HostingEnvironment.ApplicationVirtualPath);
            SessionStateConfig =
              (SessionStateSection)cfg.GetSection("system.web/sessionState");
        }
        public override void InitializeRequest(HttpContext context)
        {
            redisConnection = RedisConnection.Create(new Uri("http://192.169.0.43/"), 0);
        }

        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            //redisConnection.Open();
            //byte[] sessionStateItemCollectionBuffer = Serialize((SessionStateItemCollection)context.Session);
            ////无论是新项还是旧项都是SET操作
            //StringCommand stringCommand = redisConnection.CreateStringCommand();
            //stringCommand.Set(string.Format("{0}_{1}", sessionKeyPrefix, id), sessionStateItemCollectionBuffer, this.SessionStateConfig.Timeout.Minutes * 60);
            //redisConnection.Close();
        }

        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            throw new NotImplementedException();
        }

        public override void ResetItemTimeout(HttpContext context, string id)
        {
            redisConnection.Open();
            KeyCommand keyCommand = redisConnection.CreateKeyCommand();
            keyCommand.Expire(string.Format("{0}_{1}", sessionKeyPrefix, id), (long)SessionStateConfig.Timeout.TotalSeconds);
            redisConnection.Close();
        }
        private byte[] Serialize(SessionStateItemCollection items)
        {
            if (items == null || items.Count == 0)
            {
                return new byte[0];
            }
            Dictionary<string, object> itemDic = new Dictionary<string, object>();
            foreach (var key in items.Keys)
            {
                itemDic.Add((string)key, items[(string)key]);
            }
            // return Encoding.UTF8.GetBytes("bar");
            return Encoding.UTF8.GetBytes("'" + JsonConvert.SerializeObject(itemDic) + "'");


        }
        private const string sessionKeyPrefix = "aspnetsession";
        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            if (newItem)
            {
                redisConnection.Open();
                byte[] sessionStateItemCollectionBuffer = Serialize((SessionStateItemCollection)item.Items);
                //无论是新项还是旧项都是SET操作
                StringCommand stringCommand = redisConnection.CreateStringCommand();
                stringCommand.Set(string.Format("{0}_{1}", sessionKeyPrefix, id), sessionStateItemCollectionBuffer, item.Timeout * 60);
                redisConnection.Close();
            }
        }

        public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
        {
            throw new NotImplementedException();
        }
    }

}
